using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace TicTacToe
{
    public class GameLogic
    {
        TicTacToePlayer winner;
        TicTacToePlayer current;

        TicTacToePlayer[,] grid;

        BoardSize boardSize;
        bool winnable;
        int size;
        int numToWin;//khong the = 1

        private TicTacToePlayer theFirst;

        public GameLogic(int numToWin, int size, TicTacToePlayer theFirst)
        {
            this.size = size;
            this.numToWin = numToWin;
            this.current = theFirst;
            this.winner = TicTacToePlayer.None;
            this.winnable = true;

            grid = new TicTacToePlayer[size, size];
            for (int i = 0; i < size; i++)
            {
                for (int j = 0; j < size; j++)
                {
                    grid[i, j] = TicTacToePlayer.None;
                }
            }
        }

        public GameLogic(TicTacToePlayer[,] grid, int numToWin, int size, TicTacToePlayer theFirst, bool winnable, TicTacToePlayer winner)
        {
            this.grid = (TicTacToePlayer[,])grid.Clone();
            this.numToWin = numToWin;
            this.size = size;
            this.theFirst = theFirst;
            this.winnable = winnable;
            this.winner = winner;
        }

        public TicTacToePlayer Current
        {
            get { return current; }
        }

        public bool Winnable
        {
            get { return winnable; }
        }

        public TicTacToePlayer Winner
        {
            get { return winner; }
        }

        public int NumToWin
        {
            get { return numToWin; }
            set { numToWin = value; }
        }

        public TicTacToePlayer[,] Grid
        {
            get { return grid; }
        }

        public void CheckForWin(TicTacToePlayer player)
        {
            CheckWinOnColumn(player);
            CheckWinOnRow(player);
            CheckWinOnLeftToRight(player);
            CheckWinOnRightToLeft(player);
        }

        private void CheckWinOnLeftToRight(TicTacToePlayer player)
        {
            for (int j = size - numToWin; j >= 0; j--)
            {
                int dem = 1;
                int demDX = 1;
                bool startCount = false;
                bool startCountDX = false;
                TicTacToePlayer c = TicTacToePlayer.None;
                TicTacToePlayer cDX = TicTacToePlayer.None;
                for (int i = 0, k = j; i < size - j; i++, k++)
                {
                    if (grid[i, k] == TicTacToePlayer.None)
                    {
                        startCount = false;
                    }
                    else if (!startCount)
                    {
                        startCount = true;
                        c = grid[i, k];
                        dem = 1;
                        continue;
                    }

                    if (startCount)
                    {
                        if (grid[i, k] == c)
                        {
                            dem++;
                        }
                        else
                        {
                            dem = 1;
                            c = grid[i, k];
                        }
                    }


                    // phan doi xung
                    if (grid[k, i] == TicTacToePlayer.None)
                    {
                        startCountDX = false;
                    }
                    else if (!startCountDX)
                    {
                        startCountDX = true;
                        cDX = grid[k, i];
                        demDX = 1;
                        continue;
                    }

                    if (startCountDX)
                    {
                        if (grid[k, i] == cDX)
                        {
                            demDX++;
                        }
                        else
                        {
                            demDX = 1;
                            cDX = grid[k, i];
                        }
                    }

                    if (dem == numToWin || demDX == numToWin)
                    {
                        winner = player;
                        return;
                    }
                }
            }
        }

        private void CheckWinOnRightToLeft(TicTacToePlayer player)
        {
            for (int j = size - 1; j >= numToWin - 1; j--)
            {
                int dem = 1;
                int demDX = 1;
                bool startCount = false;
                bool startCountDX = false;
                TicTacToePlayer c = TicTacToePlayer.None;
                TicTacToePlayer cDX = TicTacToePlayer.None;
                for (int i = 0, k = j; i <= j; i++, k--)
                {
                    if (grid[i, k] == TicTacToePlayer.None)
                    {
                        startCount = false;
                    }
                    else if (!startCount)
                    {
                        startCount = true;
                        c = grid[i, k];
                        dem = 1;
                        continue;
                    }

                    if (startCount)
                    {
                        if (grid[i, k] == c)
                        {
                            dem++;
                        }
                        else
                        {
                            dem = 1;
                            c = grid[i, k];
                        }
                    }


                    // phan doi xung
                    int iDX = size - k - 1;
                    int jDX = size - i - 1;
                    if (grid[iDX, jDX] == TicTacToePlayer.None)
                    {
                        startCountDX = false;
                    }
                    else if (!startCountDX)
                    {
                        startCountDX = true;
                        cDX = grid[iDX, jDX];
                        demDX = 1;
                        continue;
                    }

                    if (startCountDX)
                    {
                        if (grid[iDX, jDX] == cDX)
                        {
                            demDX++;
                        }
                        else
                        {
                            demDX = 1;
                            cDX = grid[iDX, jDX];
                        }
                    }

                    if (dem == numToWin || demDX == numToWin)
                    {
                        winner = player;
                        return;
                    }
                }
            }
        }

        private void CheckWinOnColumn(TicTacToePlayer player)
        {
            for (int i = 0; i < size; i++)
            {
                TicTacToePlayer c = TicTacToePlayer.None;
                int j;
                for (j = 0; j <= size - numToWin; j++)
                {
                    if (grid[i, j] != TicTacToePlayer.None)
                    {
                        c = grid[i, j];
                        j++;
                        break;
                    }
                }

                int dem = 1;
                for (; j < size; j++)
                {
                    if (grid[i, j] == TicTacToePlayer.None)
                    {
                        for (; j <= size - numToWin; j++)
                        {
                            if (grid[i, j] != TicTacToePlayer.None)
                            {
                                c = grid[i, j];
                                dem = 1;
                                j++;
                                break;
                            }
                        }

                        if (j == size - numToWin + 1)
                        {
                            break;
                        }

                        continue;
                    }

                    if (grid[i, j] == c)
                    {
                        dem++;

                        if (dem == numToWin)
                        {
                            winner = player;
                            return;
                        }
                    }
                    else
                    {
                        dem = 1;
                        c = grid[i, j];
                    }
                }
            }
        }

        private void CheckWinOnRow(TicTacToePlayer player)
        {
            for (int j = 0; j < size; j++)
            {
                TicTacToePlayer c = TicTacToePlayer.None;
                int i;
                for (i = 0; i <= size - numToWin; i++)
                {
                    if (grid[i, j] != TicTacToePlayer.None)
                    {
                        c = grid[i, j];
                        i++;
                        break;
                    }
                }

                int dem = 1;
                for (; i < size; i++)
                {
                    if (grid[i, j] == TicTacToePlayer.None)
                    {
                        for (; i <= size - numToWin; i++)
                        {
                            if (grid[i, j] != TicTacToePlayer.None)
                            {
                                c = grid[i, j];
                                dem = 1;
                                i++;
                                break;
                            }
                        }

                        if (i == size - numToWin + 1)
                        {
                            break;
                        }

                        continue;
                    }

                    if (grid[i, j] == c)
                    {
                        dem++;

                        if (dem == numToWin)
                        {
                            winner = player;
                            return;
                        }
                    }
                    else
                    {
                        dem = 1;
                        c = grid[i, j];
                    }
                }
            }
        }

        public void CheckForWinnable()
        {
            if (winner == TicTacToePlayer.None)
            {
                Func<TicTacToePlayer, bool> checkNone = b => b == TicTacToePlayer.None;
                for (int i = 0; i < size; i++)
                {
                    for (int j = 0; j < size; j++)
                    {
                        if (grid[i, j] == TicTacToePlayer.None)
                        {
                            winnable = true;
                            // TODO: co the cai tien
                            return;
                        }
                    }
                }

                winnable = false;
            }
        }

        internal void SetPlayerAt(int i, int j)
        {
            grid[i, j] = current;
            current = current == TicTacToePlayer.PlayerO ? TicTacToePlayer.PlayerX : TicTacToePlayer.PlayerO;
        }

        public TicTacToePlayer GetPlayerAt(int i, int j)
        {
            return grid[i, j];
        }
    }
}
